#include<iostream>
#include<string>
#include<unistd.h>
#include<cerrno>
#include<cstring>
#include<sys/wait.h>
#include<sys/types.h>

//fork之后子进程是能拿到父进程的数据的
using namespace std;
const int _size=1024;
string GetOtherMessage()
{
    static int cnt=0;
    string messageid=to_string(cnt);
    cnt++;
    pid_t self_id=getpid();
    string stringpid=to_string(self_id);
    string message="messageid:";
    message+=messageid;
    message+=" my pid is:";
    message+=stringpid;
    return message;
}
//子进程写
void SubProcessWrite(int wfd)
{
    int pipesize=0;
    string message="father, i am your son process!";
    while(true)
    {
        string info = message+GetOtherMessage();//子进程发给父进程的消息
        write(wfd,info.c_str(),info.size());//写入管道的时候，没有写入\0，没有必要写入
        sleep(1);//子进程写慢一点
        // char c='A';
        // write(wfd,&c,1);
        // cout<<++pipesize<<endl;
        // break;
    }
}
//父进程读
void FatherProcessRead(int rfd)
{
    char inbuffer[_size];
    while(true)
    {
        ssize_t n=read(rfd,inbuffer,sizeof(inbuffer)-1);
        if(n>0)
        {
            inbuffer[n]=0;//'\0'手动添加一个\0
            cout<<"father get message:"<<inbuffer<<endl;
        }
        cout<<"return val:"<<n<<endl;
    }
}

int main()
{
    //1.创建管道
    int pipefd[2];
    int n=pipe(pipefd);//输出型参数
    if(n!=0)
    {
        cerr<<"errno:"<<errno<<"errstring:"<<strerror(errno)<<endl;
        return 1;
    }
    //pipefd[0]->0->r(读)
    //pipefd[1]->1->w(写)
    cout<<"pipefd[0]:"<<pipefd[0]<<" "<<"pipefd[1]:"<<pipefd[1]<<endl;
    sleep(1);

    //2.创建子进程
    //3.关闭不需要的文件描述符
    pid_t id=fork();
    if(id==0)
    {
        sleep(1);
        cout<<"子进程关闭不需要的fd,准备发消息"<<endl;
        //子进程---write
        close(pipefd[0]);
        SubProcessWrite(pipefd[1]);
        close(pipefd[1]);
        exit(0);
    }

    cout<<"父进程关闭不需要的fd,准备接收消息"<<endl;
    sleep(1);
    //父进程---read
    close(pipefd[1]);
    FatherProcessRead(pipefd[0]);

    close(pipefd[0]);
    pid_t rid=waitpid(id,nullptr,0);
    if(rid>0)
    {
        cout<<"wait child process done"<<endl;
    }
    return 0;
}